-module('index-of-coincidence').
-export([guess_key_length/1]).

%idea: I'll guess one key length (I could generate a list of key lengths instead).
guess_key_length(String) ->
    guess_key_length_hlpr(String, 0, 1000000, 0).

guess_key_length_hlpr(String, 25, MinSquares, MSoFar) ->
    IoCs = indexes_of_coincidence(25, String),
    SumSquares = sum_squares(IoCs, 0.065),
    if
	SumSquares < MinSquares ->
	    25;
	SumSquares >= MinSquares ->
	    MSoFar
    end ;
guess_key_length_hlpr(String, M, MinSquares, MSoFar) ->
    IoCs = indexes_of_coincidence(M, String),
    SumSquares = sum_squares(IoCs, 0.065),
    if
	SumSquares < MinSquares ->
	    guess_key_length_hlpr(String, M + 1, SumSquares, M);
	SumSquares >= MinSquares ->
	    guess_key_length_hlpr(String, M + 1, MinSquares, MSoFar)
    end.

sum_squares(List, FixedValue) ->
    sum_squares_hlpr(List, FixedValue, 0).

sum_squares_hlpr([H], FixedValue, SumSoFar) ->
    SumSoFar + (H - FixedValue)*(H - FixedValue) ;
sum_squares_hlpr([H|T], FixedValue, SumSoFar) ->
    sum_squares_hlpr(T, FixedValue, SumSoFar + (H - FixedValue)*(H - FixedValue)).
    

indexes_of_coincidence(M,String) ->
    Strings = columns:getMatrix(M, String),
    indexes_of_coincidence_helper(Strings, []).

indexes_of_coincidence_helper([H|T], IoCs) ->
    indexes_of_coincidence_helper(T, [index_of_coincidence(H)|IoCs]);
indexes_of_coincidence_helper([], IoCs) ->
    IoCs.    

index_of_coincidence(CharList) when length(CharList) > 1 ->
    Freq = frequencies:frequencies(CharList),
    N = length(CharList),
    if
	N > 1 ->
	    compute_IoC(Freq, N, 0) ;	      
	N =< 1 ->
	    0 
						%not sure about what happens here, ask?
    end.
	
	
compute_IoC([H|T], N, IoC) ->        
    compute_IoC(T, N, IoC + H * (H - 1)) ;
compute_IoC([], N, IoC) ->
    IoC / (N*(N-1)).
  
